home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / pvm34b3.zip / pvm34b3 / pvm3 / src / lpvmcat.c < prev    next >
C/C++ Source or Header  |  1997-07-22  |  10KB  |  470 lines

  1.  
  2. static char rcsid[] =
  3.     "$Id: lpvmcat.c,v 1.7 1997/06/27 17:32:24 pvmsrc Exp $";
  4.  
  5. /*
  6.  *         PVM version 3.4:  Parallel Virtual Machine System
  7.  *               University of Tennessee, Knoxville TN.
  8.  *           Oak Ridge National Laboratory, Oak Ridge TN.
  9.  *                   Emory University, Atlanta GA.
  10.  *      Authors:  J. J. Dongarra, G. E. Fagg, M. Fischer
  11.  *          G. A. Geist, J. A. Kohl, R. J. Manchek, P. Mucci,
  12.  *         P. M. Papadopoulos, S. L. Scott, and V. S. Sunderam
  13.  *                   (C) 1997 All Rights Reserved
  14.  *
  15.  *                              NOTICE
  16.  *
  17.  * Permission to use, copy, modify, and distribute this software and
  18.  * its documentation for any purpose and without fee is hereby granted
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both the copyright notice and this permission notice appear in
  21.  * supporting documentation.
  22.  *
  23.  * Neither the Institutions (Emory University, Oak Ridge National
  24.  * Laboratory, and University of Tennessee) nor the Authors make any
  25.  * representations about the suitability of this software for any
  26.  * purpose.  This software is provided ``as is'' without express or
  27.  * implied warranty.
  28.  *
  29.  * PVM version 3 was funded in part by the U.S. Department of Energy,
  30.  * the National Science Foundation and the State of Tennessee.
  31.  */
  32.  
  33. /*
  34.  *    lpvmcat.c
  35.  *
  36.  *    Child task output collection.
  37.  *
  38. $Log: lpvmcat.c,v $
  39.  * Revision 1.7  1997/06/27  17:32:24  pvmsrc
  40.  * Updated for WIN32 header files & Authors.
  41.  *
  42.  * Revision 1.6  1997/06/12  20:10:40  pvmsrc
  43.  * Made sure all communications for TC_* task control messages
  44.  *     use the SYSCTX_TC system context.
  45.  *     - some messages being sent in default context...  D-Oh...
  46.  *
  47.  * Revision 1.5  1997/04/07  21:09:20  pvmsrc
  48.  * pvm_addmhf() - new paramter interface
  49.  *
  50.  * Revision 1.4  1997/01/28  19:26:24  pvmsrc
  51.  * New Copyright Notice & Authors.
  52.  *
  53.  * Revision 1.3  1996/10/25  13:57:23  pvmsrc
  54.  * Replaced old #includes for protocol headers:
  55.  *     - <pvmsdpro.h>, "ddpro.h", "tdpro.h"
  56.  * With #include of new combined header:
  57.  *     - <pvmproto.h>
  58.  *
  59.  * Revision 1.2  1996/10/24  21:18:29  pvmsrc
  60.  * Moved #include "global.h" to end of #include's for typing.
  61.  * Added #include of new "lpvm.h" in place of explicitly extern-ed
  62.  *     globals...
  63.  *
  64.  * Revision 1.1  1996/09/23  23:44:13  pvmsrc
  65.  * Initial revision
  66.  *
  67.  * Revision 1.7  1995/11/02  16:08:12  manchek
  68.  * added NEEDSENDIAN switch
  69.  *
  70.  * Revision 1.6  1995/07/28  16:04:05  manchek
  71.  * switch endian includes on flag, not arch name
  72.  *
  73.  * Revision 1.5  1995/05/17  16:17:24  manchek
  74.  * fixed buf in pvmclaimo, copying one byte too few
  75.  *
  76.  * Revision 1.4  1994/12/20  16:35:57  manchek
  77.  * added ShowTids option
  78.  *
  79.  * Revision 1.3  1994/11/07  21:34:49  manchek
  80.  * cast message tag for comparison as int
  81.  *
  82.  * Revision 1.2  1994/10/15  19:10:08  manchek
  83.  * don't segfault if we get a TC_OUTPUT message and pvm_catchout never called
  84.  *
  85.  * Revision 1.1  1994/06/03  20:38:16  manchek
  86.  * Initial revision
  87.  *
  88.  */
  89.  
  90.  
  91. #include <stdio.h>
  92. #ifdef NEEDMENDIAN
  93. #include <machine/endian.h>
  94. #endif
  95. #ifdef NEEDENDIAN
  96. #include <endian.h>
  97. #endif
  98. #ifdef NEEDSENDIAN
  99. #include <sys/endian.h>
  100. #endif
  101. #ifndef WIN32
  102. #include <rpc/types.h>
  103. #include <rpc/xdr.h>
  104. #else 
  105. #include "..\xdr\types.h"
  106. #include "..\xdr\xdr.h"
  107. #endif
  108. #ifdef    SYSVSTR
  109. #include <string.h>
  110. #define    CINDEX(s,c)    strchr(s,c)
  111. #else
  112. #include <strings.h>
  113. #define    CINDEX(s,c)    index(s,c)
  114. #endif
  115. #include <signal.h>
  116. #include <pvm3.h>
  117. #include <pvmproto.h>
  118. #include "pvmalloc.h"
  119. #include "listmac.h"
  120. #include "bfunc.h"
  121. #include "tvdefs.h"
  122. #include "lpvm.h"
  123. #include <pvmtev.h>
  124. #include "tevmac.h"
  125. #include "global.h"
  126.  
  127.  
  128. /*
  129. *    used to collect output from a task
  130. */
  131.  
  132. struct tobuf {
  133.     struct tobuf *o_link, *o_rlink;        /* chain of all tasks in job */
  134.     int o_tid;                            /* task id */
  135.     int o_len;                            /* length of buf */
  136.     char *o_buf;                        /* buffered partial line */
  137.     int o_maxl;                            /* space in buf */
  138.     int o_flag;                            /* task state */
  139. #define    GOTSPAWN    1
  140. #define    GOTEOF        2
  141. #define    GOTBOTH        (GOTSPAWN|GOTEOF)
  142. #define    TASKSTATE    (GOTSPAWN|GOTEOF)
  143. };
  144.  
  145.  
  146. /***************
  147.  **  Globals  **
  148.  **           **
  149.  ***************/
  150.  
  151.  
  152. /***************
  153.  **  Private  **
  154.  **           **
  155.  ***************/
  156.  
  157. static struct tobuf *tobuflist = 0;
  158. static FILE *outlogff = 0;
  159.  
  160.  
  161. /**************************
  162.  **  Internal Functions  **
  163.  **                      **
  164.  **************************/
  165.  
  166. static int pvmclaimo();
  167. static int pvmflusho();
  168.  
  169. static int
  170. tobuf_init()
  171. {
  172.     int i;
  173.     struct pvmminfo minfo;
  174.     int ictx;
  175.  
  176.     if (!tobuflist) {
  177.         tobuflist = TALLOC(1, struct tobuf, "obuf");
  178.         BZERO((char*)tobuflist, sizeof(struct tobuf));
  179.         tobuflist->o_link = tobuflist->o_rlink = tobuflist;
  180.  
  181.         i = pvm_setopt(PvmResvTids, 1);
  182.  
  183.         BZERO(&minfo, sizeof(minfo));
  184.         minfo.src = -1;
  185.         minfo.ctx = SYSCTX_TC;
  186.         minfo.tag = TC_OUTPUT;
  187.         pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvmclaimo);
  188.         minfo.tag = TC_OUTPUTX;
  189.         pvm_addmhf(minfo.src, minfo.tag, minfo.ctx, pvmflusho);
  190.  
  191.         ictx = pvm_setcontext(SYSCTX_TC);
  192.         pvm_notify(PvmTaskExit, TC_OUTPUTX, 1, &pvmmytid);
  193.         pvm_setcontext(ictx);
  194.  
  195.         pvm_setopt(PvmResvTids, i);
  196.     }
  197.     return 0;
  198. }
  199.  
  200.  
  201. static struct tobuf *
  202. tobuf_new(tid)
  203.     int tid;
  204. {
  205.     struct tobuf *op = tobuflist->o_link;
  206.     struct tobuf *op2;
  207.  
  208.     while (op != tobuflist && op->o_tid < tid)
  209.         op = op->o_link;
  210.     if (op->o_tid != tid) {
  211.         op2 = TALLOC(1, struct tobuf, "tobuf");
  212.         BZERO((char*)op2, sizeof(struct tobuf));
  213.         op2->o_tid = tid;
  214.         LISTPUTBEFORE(op, op2, o_link, o_rlink);
  215.         op = op2;
  216.     }
  217.     return op;
  218. }
  219.  
  220.  
  221. static int
  222. tobuf_free(op)
  223.     struct tobuf *op;
  224. {
  225.     LISTDELETE(op, o_link, o_rlink);
  226.     if (op->o_buf)
  227.         PVM_FREE(op->o_buf);
  228.     PVM_FREE(op);
  229.     return 0;
  230. }
  231.  
  232.  
  233. static struct tobuf *
  234. tobuf_find(tid)
  235.     int tid;
  236. {
  237.     struct tobuf *op = tobuflist->o_link;
  238.  
  239.     while (op != tobuflist && op->o_tid < tid)
  240.         op = op->o_link;
  241.     if (op->o_tid == tid)
  242.         return op;
  243.     return (struct tobuf*)0;
  244. }
  245.  
  246.  
  247. /*    pvmflusho()
  248. *
  249. *    Called by pvm_exit() to make sure all task output is flushed.
  250. *    If outlogff is nonzero, make sure all child tasks have exited
  251. *    else just toss the output.
  252. */
  253.  
  254. static int
  255. pvmflusho()
  256. {
  257.     struct tobuf *op;
  258.     int cc;
  259.  
  260.     if (outlogff) {
  261.         if (tobuflist && tobuflist->o_link != tobuflist) {
  262.             if (pvmshowtaskid)
  263.                 pvmlogerror("child task(s) still running.  waiting...\n");
  264.             while (tobuflist->o_link != tobuflist) {
  265.  
  266.     /* XXX mroute() does return after ctrl messages received */
  267.  
  268.                 if ((cc = mroute(0, 0, 0, (struct timeval *)0)) < 0)
  269.                     break;
  270.             }
  271.         }
  272.         pvm_catchout((FILE *)0);
  273.     }
  274.  
  275.     if (tobuflist) {
  276.         while (tobuflist->o_link != tobuflist)
  277.             tobuf_free(tobuflist->o_link);
  278.         PVM_FREE(tobuflist);
  279.         tobuflist = 0;
  280.     }
  281.     return 0;
  282. }
  283.  
  284.  
  285. /*    pvmclaimo()
  286. *
  287. *    We get output from a child* task (because we called pvm_catchout())
  288. *
  289. *    TC_OUTPUT() {
  290. *        int tid                // of source task
  291. *        int length            // of output
  292. *        char output[length]    // characters printed
  293. *    }
  294. */
  295.  
  296. static int
  297. pvmclaimo(mid)
  298.     int mid;
  299. {
  300.     int tid;                    /* task */
  301.     int n;                        /* length or event code */
  302.     char *p;
  303.     int ptid;
  304.     struct tobuf *op;
  305.     int rbf;
  306.  
  307.     rbf = pvm_setrbuf(mid);
  308.  
  309. /*
  310.     if (TRACE) {
  311.         checktrace(jp, cc, len, cod, src);
  312.         return 0;
  313.     }
  314. */
  315.  
  316.     pvm_upkint(&tid, 1, 1);
  317.     pvm_upkint(&n, 1, 1);
  318.  
  319.     if (!tobuflist) {
  320.         pvmlogprintf("pvmclaimo() message from task t%x\n", tid);
  321.         goto done;
  322.     }
  323.  
  324.     if (n > 0) {    /* output printed by task */
  325.         if (!(op = tobuf_find(tid))) {
  326.             pvmlogprintf("pvmclaimo() bogus message, no task t%x\n", tid);
  327.             goto done;
  328.         }
  329.         if (n + op->o_len >= op->o_maxl) {
  330.             op->o_maxl = op->o_len + n + 1;
  331. /*
  332.             printf("REALLOC t%x buf to %d\n", tid, op->o_maxl);
  333. */
  334.             if (op->o_buf)
  335.                 op->o_buf = TREALLOC(op->o_buf, op->o_maxl, char);
  336.             else
  337.                 op->o_buf = TALLOC(op->o_maxl, char, "");
  338.         }
  339.         pvm_upkbyte(op->o_buf + op->o_len, n, 1);
  340.         op->o_buf[op->o_len + n] = 0;
  341. /*
  342.         printf("UNPACK t%x {%s}\n", tid, op->o_buf + op->o_len);
  343. */
  344.         p = op->o_buf + op->o_len;
  345.         op->o_len += n;
  346. /* XXX would be more efficient to remove all lines before copying remainder */
  347.         while (p = CINDEX(p, '\n')) {
  348.             *p++ = 0;
  349.             if (outlogff)
  350.                 if (pvmshowtaskid)
  351.                     fprintf(outlogff, "[t%x] %s\n", tid, op->o_buf);
  352.                 else
  353.                     fprintf(outlogff, "%s\n", op->o_buf);
  354.             op->o_len -= p - op->o_buf;
  355.             BCOPY(p, op->o_buf, op->o_len + 1);
  356.             p = op->o_buf;
  357.         }
  358.  
  359.     } else {
  360.         switch (n) {
  361.  
  362.         case 0:        /* EOF from task */
  363.             if (!(op = tobuf_find(tid))) {
  364.                 pvmlogprintf("pvmclaimo() bogus message, no task t%x\n", tid);
  365.                 goto done;
  366.             }
  367.             if (op->o_len > 0) {
  368.                 if (outlogff)
  369.                     if (pvmshowtaskid)
  370.                         fprintf(outlogff, "[t%x] %s\n", tid, op->o_buf);
  371.                     else
  372.                         fprintf(outlogff, "%s\n", op->o_buf);
  373.                 op->o_len = 0;
  374.             }
  375.             op->o_flag |= GOTEOF;
  376.             if ((op->o_flag & TASKSTATE) == GOTBOTH) {
  377.                 if (outlogff && pvmshowtaskid)
  378.                     fprintf(outlogff, "[t%x] EOF\n", tid);
  379.                 tobuf_free(op);
  380.             }
  381.             break;
  382.  
  383.         case -1:    /* spawn creating new task */
  384.             if (!(op = tobuf_find(tid))) {
  385.                 op = tobuf_new(tid);
  386.                 if (outlogff && pvmshowtaskid)
  387.                     fprintf(outlogff, "[t%x] BEGIN\n", tid);
  388.             }
  389.             op->o_flag |= GOTSPAWN;
  390.             if ((op->o_flag & TASKSTATE) == GOTBOTH) {
  391.                 if (outlogff && pvmshowtaskid)
  392.                     fprintf(outlogff, "[t%x] EOF\n", tid);
  393.                 tobuf_free(op);
  394.             }
  395.  
  396.             break;
  397.  
  398.         case -2:    /* new task starting up */
  399.             if (!(op = tobuf_find(tid))) {
  400.                 op = tobuf_new(tid);
  401.                 if (outlogff && pvmshowtaskid)
  402.                     fprintf(outlogff, "[t%x] BEGIN\n", tid);
  403.             }
  404.             break;
  405.  
  406.         default:
  407.             pvmlogprintf("pvmclaimo() bogus message from task t%x\n", tid);
  408.             break;
  409.         }
  410.     }
  411.  
  412. done:
  413.     pvm_setrbuf(rbf);
  414.     pvm_freebuf(mid);
  415.     return 0;
  416. }
  417.  
  418.  
  419. /**************************
  420.  **  Exported Functions  **
  421.  **                      **
  422.  **************************/
  423.  
  424. int
  425. tobuf_dump()
  426. {
  427.     struct tobuf *op;
  428.  
  429.     if (tobuflist)
  430.         for (op = tobuflist->o_link; op != tobuflist; op = op->o_link) {
  431.             printf("tobuf_dump() t%x\n", op->o_tid);
  432.         }
  433.     else
  434.         printf("tobuf_dump() tobuflist null\n");
  435.     return 0;
  436. }
  437.  
  438.  
  439. /************************
  440.  **  Libpvm Functions  **
  441.  **                    **
  442.  ************************/
  443.  
  444. /*    pvm_catchout()
  445. *
  446. *    Log output of tasks spawned by us to file.
  447. */
  448.  
  449. int
  450. pvm_catchout(ff)
  451.     FILE *ff;
  452. {
  453.     if (ff) {
  454.         tobuf_init();
  455.         pvm_setopt(PvmOutputTid, pvm_mytid());
  456.         pvm_setopt(PvmOutputContext, (int)SYSCTX_TC);
  457.         pvm_setopt(PvmOutputCode, (int)TC_OUTPUT);
  458.         outlogff = ff;
  459.  
  460.     } else {
  461.         pvm_setopt(PvmOutputCode, pvm_getopt(PvmSelfOutputCode));
  462.         pvm_setopt(PvmOutputContext, pvm_getopt(PvmSelfOutputContext));
  463.         pvm_setopt(PvmOutputTid, pvm_getopt(PvmSelfOutputTid));
  464.         outlogff = 0;
  465.     }
  466.     return PvmOk;
  467. }
  468.  
  469.  
  470.